package com.own.demo.writerfile;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.own.demo.utils.CommWriterFileInfo;
import com.own.demo.utils.DateUtils;
import com.own.demo.utils.FileToStringUtils;
import com.own.demo.vo.Bounds;
import com.own.demo.vo.NodeInfo;
import com.own.demo.vo.RoadInfo;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import java.io.BufferedWriter;
import java.io.File;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;

public class GeoJsonToOsmXML {
    private static AtomicLong indexNum = new AtomicLong(1);
    private static Map<String, NodeInfo> lonLatMap;


    public static void jsonToXML(JSONObject geoJson, Bounds bounds,String osmUrl,String fileName) {
        JSONArray jsonArray = geoJson.getJSONArray("features");
        int row = jsonArray.size();
        lonLatMap = new ConcurrentHashMap<>(row);

        for (int i = 0; i < row; i++) {
            JSONObject jsonObject = jsonArray.getJSONObject(i);
            JSONObject properties = jsonObject.getJSONObject("properties");
            String propKey = "name";
            JSONObject geometry = jsonObject.getJSONObject("geometry");
            JSONArray lonlatList = geometry.getJSONArray("coordinates");
            int lonlatSize = lonlatList.size();
            for (int j = 0; j < lonlatSize; j++) {
                JSONArray point = lonlatList.getJSONArray(j);
                double lon = point.getDouble(0);
                double lat = point.getDouble(1);
                String key = lon + "+" + lat;
                lonLatMap.put(key, new NodeInfo(properties.getString(propKey), indexNum.getAndIncrement(), propKey, lon, lat));
            }
        }

        Document document = dataDocument(bounds);
        setNode(document.getRootElement());
        for (int i = 0; i < row; i++) {
            JSONObject jsonObject = jsonArray.getJSONObject(i);
            JSONObject geometry = jsonObject.getJSONObject("geometry");
            setWay(document.getRootElement(),geometry.getJSONArray("coordinates"),jsonObject.getJSONObject("properties"),i);
        }

        String xml=document.asXML();
        document.clearContent();
        writerFoFileOSM(xml,osmUrl,fileName);
    }
    public static void writerFoFileOSM(String data,String folderPath,String fileName) {
        try {
            File folder = new File(folderPath);
            if (!folder.exists()) {
                folder.mkdirs();
            }
            BufferedWriter bufferedWriter = CommWriterFileInfo.getWriterBuffer(folderPath + "\\" + fileName, false);
            CommWriterFileInfo.writer(bufferedWriter, data);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void setNode(Element osm) {
        for (Map.Entry<String, NodeInfo> node : lonLatMap.entrySet()) {
            setNodeElement(osm, node.getValue());
        }
    }

    public static Element setNodeElement(Element osm, NodeInfo nodeInfo) {
        Element node1 = osm.addElement("node");
        node1.addAttribute("id", nodeInfo.getIndex() + "");
        node1.addAttribute("visible", true + "");
        node1.addAttribute("version", 1 + "");
        node1.addAttribute("lat", nodeInfo.getY() + "");
        node1.addAttribute("lon", nodeInfo.getX() + "");
        return node1;
    }

    public static Document dataDocument(Bounds bounds) {
        Document document = DocumentHelper.createDocument();
        Element osm = document.addElement("osm");
        osm.addAttribute("version", "0.6");
        osm.addAttribute("generator", "CGImap 0.8.8 (587855 spike-08.openstreetmap.org)");
        osm.addAttribute("copyright", "OpenStreetMap and contributors");
        osm.addAttribute("attribution", "http://www.openstreetmap.org/copyright");
        osm.addAttribute("license", "http://opendatacommons.org/licenses/odbl/1-0/");

        Element boundsEl = osm.addElement("bounds");
        boundsEl.addAttribute("minlat", bounds.getMinLat() + "");
        boundsEl.addAttribute("minlon", bounds.getMaxLon() + "");
        boundsEl.addAttribute("maxlat", bounds.getMaxLat() + "");
        boundsEl.addAttribute("maxlon", bounds.getMaxLon() + "");
        boundsEl.addAttribute("id", indexNum.getAndIncrement() + "");
        boundsEl.addAttribute("version", "1");
        return document;
    }

    public static Element setWay(Element osm, JSONArray lonlatList,JSONObject properties,int i) {
        Element way = osm.addElement("way");
        way.addAttribute("id", indexNum.getAndIncrement() + "");
        way.addAttribute("visible", true + "");
        way.addAttribute("version", 1 + "");
        int lonlatSize = lonlatList.size();
        for (int j = 0; j < lonlatSize; j++) {

            JSONArray point = lonlatList.getJSONArray(j);
            double lon = point.getDouble(0);
            double lat = point.getDouble(1);
            String key = lon + "+" + lat;
            Element nod = way.addElement("nd");
            NodeInfo nodeInfo=lonLatMap.get(key);
            nod.addAttribute("ref", nodeInfo.getIndex() + "");
        }

       if(properties !=null) {
           Set<String> keys = properties.keySet();
           Iterator<String> iterator = keys.iterator();
           while(iterator.hasNext()){
               String key = iterator.next();
               String o =properties.getString(key);
               Element tagName = way.addElement("tag");
               tagName.addAttribute("k", key);
               tagName.addAttribute("v", o);
           }
           Element tagRoadType = way.addElement("tag");
           tagRoadType.addAttribute("k", "highway");
           tagRoadType.addAttribute("v", "motorway");
       }
        return way;
    }
}
